#ifndef SEM_HPP
#define SEM_HPP

#include<iostream>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/types.h>
#include<memory>
using namespace std;

const string sem_path ="/tmp";
const int sem_proj_id=0x777;
const int defaultnum=1;

#define GET_SEM(IPC_CREAT)
#define BUILD_SEM (IPC_CREAT |IPC_EXCL|0666)


//把整数转16进制的函数
string Tohex(int num)
{
    char hex[64];
    snprintf(hex,sizeof(hex),"0x%x",num);
    return string(hex);
}
//封装一个信号量
class Semaphore
{
    // public:
    // struct sembuf{
    //     unsigned short sem_num;//信号量数字
    //     short op;
    //     short flag;//
    // };
    void PV(int data)
    {
        struct sembuf mybuf;
        mybuf.sem_num=0;
        mybuf.sem_op=data;
        mybuf.sem_flg=SEM_UNDO;
        int n=semop(_semid,&mybuf,1);
        if(n<0)
        {
            cerr<<"sem P failed"<<endl;
        }

    }
    public:
    
    Semaphore(int semid):_semid(semid){}
    void P()
    {
       PV(-1);
    }
    void V()
    {
        PV(1);
    }
    ~Semaphore(){
        if(_semid>=0)
        {
            int n=semctl(_semid,0,IPC_RMID);
            if(n<0)
            {
                cerr<<"ipc failed"<<endl;
            }
            cout<<"semaphore:"<<_semid<<"removed"<<endl;
        }

    }
    private:
    int _semid;
};

//简单的建造者模式
class SemaphoreBuilder
{
    public:
    SemaphoreBuilder(){}
    ~SemaphoreBuilder(){}
    bool init(int semid,int i) //下标
    {
       union semun {
               int  val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
        }un;
        un.val=1;
        int n=semctl(semid,i,SETVAL,un);
        if(n<0)
        {
            cerr<<"semctl SETVAL failed"<<endl;
            return false;
        }
        return true;
    }

    Semaphore* Setval()
    {
        
    }
    std::shared_ptr<Semaphore>build(int flag,int num=defaultnum)
    {
        cout<<"build a semaphore....."<<endl;
        //构建键值
        key_t k=ftok(sem_path.c_str(),sem_proj_id);
        if(k<0)
        {
            cerr<<"ftok failed!"<<endl;
        }
        cout<<"get key:"<< Tohex(k)<<endl;
        //构建信号量集合
        int semid=semget(k,num,flag);
        if(semid<0)
        {
            cerr<<"semid failed!"<<endl;
            return nullptr;
        }
        cout<<"got semaphore id:"<<semid<<endl;

        //初始化
        init(semid,0);

        return make_shared<Semaphore>(semid);
    }
    
    private:
    

};


/////////////////////////////////////////////建造者模式
//建造者接口
class SemphoreBuilder
{
    public:

};

//具体建造者类
class ConSemaphoreBuilder
{
    public:
    private:
    shared_ptr<SemaphoreBuilder> _sem;
};
//指挥者类
class Director{
    public:
    private:

};
#endif